using S7.Net;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace 西门子PLC数据采集
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            //PLC的型号
            ModelText.DataSource = Enum.GetNames(typeof(CpuType));
            ModelText.SelectedIndex = 0;
            TypeText.DataSource = Enum.GetNames(typeof(DataType));

            //读取数据类型
            TypeText.SelectedIndex = 0;
        }

        /// <summary>
        /// PLC对象
        /// </summary>
        S7PLC? plc;

        private void Form1_Load(object sender, EventArgs e)
        {

           
            InterfaceStatus(0);
            VersionText.Text = "Ver：2024.03.08";
        }

        /// <summary>
        /// 连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnConnect_Click(object sender, EventArgs e)
        {
            CpuType cpuType = (CpuType)Enum.Parse(typeof(CpuType), ModelText.Text, true);

            plc = new(cpuType, IPText.Text, short.Parse(RackText.Text), short.Parse(SlotText.Text));

            plc!.OperationEvent += AppText;

            plc.Connect();

            if (plc.IsConnected)
            {
                InterfaceStatus(1);
            }
        }

        /// <summary>
        /// 断开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            if (plc is not null)
            {
                plc.Close();

                InterfaceStatus(0);
            }
        }

        /// <summary>
        /// 读取
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRead_Click(object sender, EventArgs e)
        {
            DataType dataType = (DataType)Enum.Parse(typeof(DataType), TypeText.Text, true);

            object value = plc!.Read(dataType, AddressText.Text.ToUpper());

            ValueText.Text = value.ToString();
        }

        /// <summary>
        /// 写入
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnWrite_Click(object sender, EventArgs e)
        {
            DataType dataType = (DataType)Enum.Parse(typeof(DataType), TypeText.Text, true);

            plc!.Write(dataType, AddressText.Text.ToUpper(), ValueText.Text);
        }

        /// <summary>
        /// 日志
        /// </summary>
        /// <param name="str"></param>
        public void AppText(string str)
        {
            this.Invoke(new Action(() =>
            {
                LogText.AppendText($"{str}\r\n");
            }));
        }

        /// <summary>
        /// 界面状态
        /// </summary>
        public void InterfaceStatus(int number)
        {
            if (number == 0)
            {
                btnConnect.Enabled = true;
                btnDisconnect.Enabled = false;
                groupBox1.Enabled = true;
                groupBox2.Enabled = false;
                groupBox3.Enabled = false;
                groupBox4.Enabled = false;
            }
            if (number == 1)
            {
                btnConnect.Enabled = false;
                btnDisconnect.Enabled = true;
                groupBox1.Enabled = false;
                groupBox2.Enabled = true;
                groupBox3.Enabled = true;
                groupBox4.Enabled = true;
            }

            if (number == 30)
            {
                //读
                btnLoopReadS.Enabled = true;
                btnLoopReadE.Enabled = false;
                //写
                btnLoopWriteS.Enabled = true;
                btnLoopWriteE.Enabled = false;
                //增减写
                btnDeviationValueS.Enabled = true;
                btnDeviationValueE.Enabled = false;

            }
            if (number == 31)
            {
                //读
                btnLoopReadS.Enabled = false;
                btnLoopReadE.Enabled = true;
                //写
                btnLoopWriteS.Enabled = false;
                btnLoopWriteE.Enabled = false;
                //增减写
                btnDeviationValueS.Enabled = false;
                btnDeviationValueE.Enabled = false;
            }
            if (number == 32)
            {
                //读
                btnLoopReadS.Enabled = false;
                btnLoopReadE.Enabled = false;
                //写
                btnLoopWriteS.Enabled = false;
                btnLoopWriteE.Enabled = true;
                //增减写
                btnDeviationValueS.Enabled = false;
                btnDeviationValueE.Enabled = false;
            }
            if (number == 33)
            {
                //读
                btnLoopReadS.Enabled = false;
                btnLoopReadE.Enabled = false;
                //写
                btnLoopWriteS.Enabled = false;
                btnLoopWriteE.Enabled = false;
                //增减写
                btnDeviationValueS.Enabled = false;
                btnDeviationValueE.Enabled = true;
            }

        }

        /// <summary>
        /// 清空
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClean_Click(object sender, EventArgs e)
        {
            LogText.Text = "";
        }


        bool ContinuousState = false;
        /// <summary>
        /// 循环读
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLoopReadS_Click(object sender, EventArgs e)
        {
            new Task(() =>
            {
                ContinuousState = true;

                while (ContinuousState)
                {
                    this.Invoke(new Action(() =>
                    {
                        DataType dataType = (DataType)Enum.Parse(typeof(DataType), TypeText.Text, true);

                        plc!.Read(dataType, AddressText.Text.ToUpper());
                    }));

                    Thread.Sleep(int.Parse(DelayText.Text) * 100);
                }
            }).Start();

            InterfaceStatus(31);
        }

        private void btnLoopReadE_Click(object sender, EventArgs e)
        {
            ContinuousState = false;

            InterfaceStatus(30);
        }


        /// <summary>
        /// 循环写
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLoopWriteS_Click(object sender, EventArgs e)
        {

            new Task(() =>
            {
                ContinuousState = true;

                while (ContinuousState)
                {
                    this.Invoke(new Action(() =>
                    {
                        DataType dataType = (DataType)Enum.Parse(typeof(DataType), TypeText.Text, true);


                        plc!.Write(dataType, AddressText.Text.ToUpper(), ValueText.Text);
                    }));

                    Thread.Sleep(int.Parse(DelayText.Text) * 100);
                }
            }).Start();

            InterfaceStatus(32);
        }

        private void btnLoopWriteE_Click(object sender, EventArgs e)
        {
            ContinuousState = false;
            InterfaceStatus(30);
        }


        /// <summary>
        /// 增减写
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDeviationValueS_Click(object sender, EventArgs e)
        {
            //偏差值延迟
            int p = int.Parse(DeviationDelayText.Text);

            new Task(() =>
            {
                ContinuousState = true;

                while (ContinuousState)
                {
                    this.Invoke(new Action(() =>
                    {
                        DataType dataType = (DataType)Enum.Parse(typeof(DataType), TypeText.Text, true);

                        plc!.Write(dataType, AddressText.Text.ToUpper(), ValueText.Text);
                    }));

                    Thread.Sleep(int.Parse(DelayText.Text) * 100);
                }
            }).Start();

            new Task(() =>
            {
                var d = int.Parse(DeviationValueText.Text);
                var v = int.Parse(ValueText.Text);

                while (ContinuousState)
                {
                    this.Invoke(new Action(() =>
                    {
                        ValueText.Text = v.ToString();
                    }));

                    Thread.Sleep(p * 100);
                    v = v + d;
                }
            }).Start();

            InterfaceStatus(33);
        }

        private void btnDeviationValueE_Click(object sender, EventArgs e)
        {
            ContinuousState = false;
            InterfaceStatus(30);
        }

        /// <summary>
        /// 数据地址改变后验证
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AddressText_TextChanged(object sender, EventArgs e)
        {
            string addr = AddressText.Text.ToUpper();

            if (addr.Contains("DBB") || addr.Contains("QB") || addr.Contains("IB") || addr.Contains("MB"))
            {
                TypeText.SelectedIndex = 1;
            }
            else if (addr.Contains("DBW") || addr.Contains("QW") || addr.Contains("IW") || addr.Contains("MW"))
            {
                TypeText.SelectedIndex = 2;
            }
            else if (addr.Contains("DBD") || addr.Contains("QD") || addr.Contains("ID") || addr.Contains("MD"))
            {
                TypeText.SelectedIndex = 6;
            }
            else if (addr.Contains("DBX") || addr.Contains("Q") || addr.Contains("I") || addr.Contains("M"))
            {
                TypeText.SelectedIndex = 0;
            }
            else
            {
                TypeText.SelectedIndex = 0;
            }
        }

        /// <summary>
        /// 验证IP地址
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void IPText_TextChanged(object sender, EventArgs e)
        {
            if (S7PLC.IsValidIpAddress(IPText.Text))
            {
                IPText.BackColor = Color.White;
            }
            else
            {
                IPText.BackColor = Color.Red;
            }
        }

        private void btnTopping_Click(object sender, EventArgs e)
        {
            if (this.TopMost)
            {
                this.TopMost = false;
                btnTopping.Text = "置顶";
            }
            else
            {
                this.TopMost = true;
                btnTopping.Text = "取消置顶";
            }
        }
    }
}
